using System.Diagnostics;
using System.Text;
using MultiAgentsShared;

namespace MultiAgentsClient.Tools;


public struct CmdResult
{
    public string Output { get; set; }
    public string Error { get; set; }
    public int ExitCode { get; set; }

    public override readonly string ToString()
    {
        return
            $"Output: {Output}\n" +
            $"Error: {Error}\n" +
            $"ExitCode: {ExitCode}\n";
    }
}


[GptToolSet("Command Line ToolSet", "")]
public class CmdToolProvider
{
    public static CmdResult ExecuteCommand(
        string fileName,
        string command,
        string workingDirectory = "")
    {
        ProcessStartInfo startInfo = new()
        {
            FileName = fileName,
            Arguments = command,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            UseShellExecute = false,
            CreateNoWindow = true,
            WorkingDirectory = workingDirectory,
            StandardOutputEncoding = Encoding.UTF8,
            StandardErrorEncoding = Encoding.UTF8,
        };

        using Process process = new();
        process.StartInfo = startInfo;

        process.Start();
        string output = process.StandardOutput.ReadToEnd();
        string error = process.StandardError.ReadToEnd();
        process.WaitForExit();

        return new CmdResult
        {
            Output = output,
            Error = error,
            ExitCode = process.ExitCode
        };
    }

    [GptFunc("Execute command in terminal and get its outputs", true)]
    public static CmdResult ExecuteCommand(
        [GptFuncParam("command to execute")] string command,
        [GptFuncParam("the working directory to execute commands at")] string workingDirectory,
        [GptFuncParam("should run as administrator")] bool runAsAdmin)
    {
        // Find cmd.exe in the System32 folder
        string systemRoot = Environment.GetEnvironmentVariable("SystemRoot")
                            ?? throw new Exception("SystemRoot environment variable not found.");
        string cmdPath = Path.Combine(systemRoot, "System32", "cmd.exe");

        // Set up the process start info
        ProcessStartInfo startInfo = new()
        {
            FileName = cmdPath,
            Arguments = $"/c {command}", // "/c" tells cmd to execute the command string and then terminate
            WorkingDirectory = workingDirectory,
            CreateNoWindow = true, // Suppress the command window
        };

        if (runAsAdmin)
        {
            startInfo.Verb = "runas"; // Run with admin privileges
            startInfo.UseShellExecute = true; // Use shell execute to enable 'run as admin'
        }
        else
        {
            startInfo.RedirectStandardOutput = true;
            startInfo.RedirectStandardError = true;
            startInfo.StandardOutputEncoding = Encoding.UTF8;
            startInfo.StandardErrorEncoding = Encoding.UTF8;
            startInfo.UseShellExecute = false;
        }

        // Execute the process
        using Process process = new();
        process.StartInfo = startInfo;

        try
        {
            process.Start();
        }
        catch (Exception ex)
        {
            return new CmdResult
            {
                Output = string.Empty,
                Error = ex.Message,
                ExitCode = -1
            };
        }

        string output = string.Empty;
        string error = string.Empty;

        if (!runAsAdmin)
        {
            output = process.StandardOutput.ReadToEnd();
            error = process.StandardError.ReadToEnd();
        }

        process.WaitForExit();

        // Return the results
        return new CmdResult
        {
            Output = output,
            Error = error,
            ExitCode = process.ExitCode
        };
    }
}
